package cn.nexttec.noteplayer.common

import android.content.Context
import android.util.Log
import android.util.Size
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.face.FaceDetection
import com.google.mlkit.vision.face.FaceDetector
import com.google.mlkit.vision.face.FaceDetectorOptions
import java.util.concurrent.Executors
import kotlin.math.abs

class GazeTrackingController(
    private val context: Context,
    private val lifecycleOwner: LifecycleOwner,
    private val cameraFacing: CameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA,
    private val analyzeIntervalMs: Long = 500L, // 2 fps
    private val onResult: (Boolean) -> Unit
) {
    private val TAG = "GazeTrackingController"

    private var lastAnalyzeTime = 0L
    private var missingFaceCount = 0
    private val maxMissingCount = 3

    private val detector: FaceDetector = FaceDetection.getClient(
        FaceDetectorOptions.Builder()
            .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
            .enableTracking()
            .build()
    )

    private var imageAnalyzer: ImageAnalysis? = null
    private var cameraProvider: ProcessCameraProvider? = null

    fun start() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
        cameraProviderFuture.addListener({
            try {
                cameraProvider = cameraProviderFuture.get()
                Log.d(TAG, "CameraProvider ready, binding analyzer.")
                bindImageAnalyzer()
            } catch (e: Exception) {
                Log.e(TAG, "Error getting camera provider", e)
            }
        }, ContextCompat.getMainExecutor(context))
    }

    fun stop() {
        Log.d(TAG, "Stopping and unbinding camera.")
        cameraProvider?.unbindAll()
    }

    private fun bindImageAnalyzer() {
        val analyzer = ImageAnalysis.Builder()
            .setTargetResolution(Size(640, 480))
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build().also {
                it.setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy ->
                    val now = System.currentTimeMillis()
                    if (now - lastAnalyzeTime < analyzeIntervalMs) {
                        imageProxy.close()
                        return@setAnalyzer
                    }
                    lastAnalyzeTime = now

                    Log.d(TAG, "Analyzing frame at $now")

                    val mediaImage = imageProxy.image
                    if (mediaImage != null) {
                        val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)

                        detector.process(image)
                            .addOnSuccessListener { faces ->
                                Log.d(TAG, "Face detection success. Face count: ${faces.size}")
                                for (face in faces) {
                                    Log.d(TAG, "Face bounding box: ${face.boundingBox}")
                                }

                                val isLooking = faces.any { face ->
                                    val y = face.headEulerAngleY
                                    val x = face.headEulerAngleX
                                    Log.d(TAG, "Detected face angles: Y=$y, X=$x")
                                    abs(y) < 30 && abs(x) < 30
                                }

                                if (isLooking) {
                                    missingFaceCount = 0
                                    Log.d(TAG, "isLooking = true")
                                    onResult(true)
                                } else {
                                    missingFaceCount++
                                    Log.d(TAG, "isLooking = false, missingFaceCount = $missingFaceCount")
                                    if (missingFaceCount >= maxMissingCount) {
                                        onResult(false)
                                    }
                                }
                            }
                            .addOnFailureListener {
                                Log.e(TAG, "Face detection failed: ${it.message}")
                                missingFaceCount++
                                if (missingFaceCount >= maxMissingCount) {
                                    onResult(false)
                                }
                            }
                            .addOnCompleteListener {
                                imageProxy.close()
                            }
                    } else {
                        Log.w(TAG, "imageProxy.image is null")
                        imageProxy.close()
                    }
                }
            }

        try {
            cameraProvider?.unbindAll()
            cameraProvider?.bindToLifecycle(lifecycleOwner, cameraFacing, analyzer)
            imageAnalyzer = analyzer
            Log.d(TAG, "ImageAnalyzer bound to lifecycle.")
        } catch (e: Exception) {
            Log.e(TAG, "Error binding camera use case", e)
        }
    }
}
